home *** CD-ROM | disk | FTP | other *** search
- /* xlimage - xlisp memory image save/restore functions */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
- /* modified so that offset is in sizeof(node) units */
- #include "xlisp.h"
- #include <string.h>
- #include <stdlib.h>
-
- #ifdef SAVERESTORE
-
- /* external variables */
- extern LVAL obarray,xlenv,xlfenv,xldenv,s_gchook,s_gcflag;
- extern long nnodes,nfree,total;
- extern int anodes,nsegs,gccalls;
- extern struct segment *segs,*lastseg,*fixseg,*charseg;
- extern CONTEXT *xlcontext;
- extern LVAL fnodes;
-
- /* local variables */
- static OFFTYPE off,foff;
- static FILE *fp;
-
- /* forward declarations */
- #ifdef ANSI
- OFFTYPE readptr(void);
- OFFTYPE cvoptr(LVAL p);
- LVAL cviptr(OFFTYPE o);
- void freeimage(void);
- void setoffset(void);
- void writenode(LVAL node);
- void writeptr(OFFTYPE off);
- void readnode(int type, LVAL node);
- #else
- OFFTYPE readptr();
- OFFTYPE cvoptr();
- LVAL cviptr();
- VOID freeimage();
- VOID setoffset();
- VOID writenode();
- VOID writeptr();
- VOID readnode();
- #endif
-
- /* xlisave - save the memory image */
- int xlisave(fname)
- char *fname;
- {
- char fullname[STRMAX+1];
- SEGMENT *seg;
- int n,i,max;
- LVAL p;
-
- /* default the extension */
- if (needsextension(fname)) {
- strcpy(fullname,fname);
- strcat(fullname,".wks");
- fname = fullname;
- }
-
- /* open the output file */
- if ((fp = osbopen(fname,"w")) == NULL)
- return (FALSE);
-
- /* first call the garbage collector to clean up memory */
- gc();
-
- /* write out the pointer to the *obarray* symbol */
- writeptr(cvoptr(obarray));
-
- /* setup the initial file offsets */
- off = foff = (OFFTYPE)2;
-
- /* write out all nodes that are still in use */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p, off++)
- switch (ntype(p)) {
- case FREE:
- break;
- case CONS:
- case USTREAM:
- setoffset();
- fputc(p->n_type,fp);
- writeptr(cvoptr(car(p)));
- writeptr(cvoptr(cdr(p)));
- foff++;
- break;
- default:
- setoffset();
- writenode(p);
- break;
- }
- }
-
- /* write the terminator */
- fputc(FREE,fp);
- writeptr((OFFTYPE)0);
-
- /* write out data portion of SYMBOL/VECTOR/OBJECT/STRING/CLOSURE nodes */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p)
- switch (ntype(p)) {
- case SYMBOL:
- case OBJECT:
- case VECTOR:
- case CLOSURE:
- #ifdef STRUCTS
- case STRUCT:
- #endif
- max = getsize(p);
- for (i = 0; i < max; ++i)
- writeptr(cvoptr(getelement(p,i)));
- break;
- case STRING:
- max = getslength(p);
- fwrite(getstring(p),1,max,fp);
- break;
- }
- }
-
- /* close the output file */
- osclose(fp);
-
- /* return successfully */
- return (TRUE);
- }
-
- /* xlirestore - restore a saved memory image */
- int xlirestore(fname)
- char *fname;
- {
- extern FUNDEF funtab[];
- char fullname[STRMAX+1];
- int n,i,max,type;
- SEGMENT *seg;
- LVAL p;
-
- /* default the extension */
- if (needsextension(fname)) {
- strcpy(fullname,fname);
- strcat(fullname,".wks");
- fname = fullname;
- }
-
- /* open the file */
- if ((fp = osbopen(fname,"r")) == NULL)
- return (FALSE);
-
- /* free the old memory image */
- freeimage();
-
- /* initialize */
- off = (OFFTYPE)2;
- total = nnodes = nfree = 0L;
- fnodes = NIL;
- segs = lastseg = NULL;
- nsegs = gccalls = 0;
- xlenv = xlfenv = xldenv = s_gchook = s_gcflag = NIL;
- xlstack = xlstkbase + EDEPTH;
- xlfp = xlsp = xlargstkbase;
- *xlsp++ = NIL;
- xlcontext = NULL;
-
- /* create the fixnum segment */
- if ((fixseg = newsegment(SFIXSIZE)) == NULL)
- xlfatal("insufficient memory - fixnum segment");
-
- /* create the character segment */
- if ((charseg = newsegment(CHARSIZE)) == NULL)
- xlfatal("insufficient memory - character segment");
-
- /* read the pointer to the *obarray* symbol */
- obarray = cviptr(readptr());
-
- /* read each node */
- while ((type = fgetc(fp)) >= 0)
- switch (type) {
- case FREE:
- if ((off = readptr()) == (OFFTYPE)0)
- goto done;
- break;
- case CONS:
- case USTREAM:
- p = cviptr(off);
- p->n_type = type;
- #ifndef JGC
- p->n_flags = 0;
- #endif
- rplaca(p,cviptr(readptr()));
- rplacd(p,cviptr(readptr()));
- off++;
- break;
- default:
- readnode(type,cviptr(off));
- off++;
- break;
- }
- done:
-
- /* read the data portion of SYMBOL/VECTOR/OBJECT/STRING/CLOSURE nodes */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p)
- switch (ntype(p)) {
- case SYMBOL:
- case OBJECT:
- case VECTOR:
- case CLOSURE:
- #ifdef STRUCTS
- case STRUCT:
- #endif
- max = getsize(p);
- if ((p->n_vdata = (LVAL *)malloc(max * sizeof(LVAL))) == NULL)
- xlfatal("insufficient memory - vector");
- total += (long)(max * sizeof(LVAL));
- for (i = 0; i < max; ++i)
- setelement(p,i,cviptr(readptr()));
- break;
- case STRING:
- max = getslength(p);
- if ((p->n_string = malloc(max)) == NULL)
- xlfatal("insufficient memory - string");
- total += (long)max;
- fread(getstring(p),1,max,fp);
- break;
- case STREAM:
- setfile(p,NULL);
- break;
- case SUBR:
- case FSUBR:
- p->n_subr = funtab[getoffset(p)].fd_subr;
- break;
- }
- }
-
- /* close the input file */
- osclose(fp);
-
- /* collect to initialize the free space */
- gc();
-
- /* lookup all of the symbols the interpreter uses */
- xlsymbols();
-
- /* return successfully */
- return (TRUE);
- }
-
- /* freeimage - free the current memory image */
- LOCAL VOID freeimage()
- {
- SEGMENT *seg,*next;
- FILE *fp;
- LVAL p;
- int n;
-
- /* free the data portion of SYMBOL/VECTOR/OBJECT/STRING nodes */
- for (seg = segs; seg != NULL; seg = next) {
- p = &seg->sg_nodes[0];
- for (n = seg->sg_size; --n >= 0; ++p)
- switch (ntype(p)) {
- case SYMBOL:
- case OBJECT:
- case VECTOR:
- case CLOSURE:
- #ifdef STRUCTS
- case STRUCT:
- #endif
- if (p->n_vsize)
- free(p->n_vdata);
- break;
- case STRING:
- if (getslength(p))
- free(getstring(p));
- break;
- case STREAM:
- if (((fp = getfile(p)) != 0) &&
- (fp != stdin && fp != stdout && fp != stderr)) /* TAA BUG FIX */
- osclose(fp);
- break;
- }
- next = seg->sg_next;
- free(seg);
- }
- }
-
- /* setoffset - output a positioning command if nodes have been skipped */
- LOCAL VOID setoffset()
- {
- if (off != foff) {
- fputc(FREE,fp);
- writeptr(off);
- foff = off;
- }
- }
-
- /* writenode - write a node to a file */
- LOCAL VOID writenode(node)
- LVAL node;
- {
- fputc(node->n_type,fp);
- fwrite(&node->n_info, sizeof(union ninfo), 1, fp);
- foff++;
- }
-
- /* writeptr - write a pointer to a file */
- LOCAL VOID writeptr(off)
- OFFTYPE off;
- {
- fwrite(&off, sizeof(OFFTYPE), 1, fp);
- }
-
- /* readnode - read a node */
- LOCAL VOID readnode(type,node)
- int type; LVAL node;
- {
- node->n_type = type;
- #ifndef JGC
- node->n_flags = 0;
- #endif
- fread(&node->n_info, sizeof(union ninfo), 1, fp);
- }
-
- /* readptr - read a pointer */
- LOCAL OFFTYPE readptr()
- {
- OFFTYPE off;
- fread(&off, sizeof(OFFTYPE), 1, fp);
- return (off);
- }
-
- /* cviptr - convert a pointer on input */
- LOCAL LVAL cviptr(o)
- OFFTYPE o;
- {
- OFFTYPE off = (OFFTYPE)2;
- SEGMENT *seg;
-
- /* check for nil */
- if (o == (OFFTYPE)0)
- return ((LVAL)o);
-
- /* compute a pointer for this offset */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- if (o >= off && o < off + (OFFTYPE)seg->sg_size)
- return (seg->sg_nodes + o - off);
- off += (OFFTYPE)seg->sg_size;
- }
-
- /* create new segments if necessary */
- for (;;) {
-
- /* create the next segment */
- if ((seg = newsegment(anodes)) == NULL)
- xlfatal("insufficient memory - segment");
-
- /* check to see if the offset is in this segment */
- if (o >= off && o < off + (OFFTYPE)seg->sg_size)
- return (seg->sg_nodes + o - off);
- off += (OFFTYPE)seg->sg_size;
- }
- }
- #ifdef __ZTC__
- /* Special version for Zortech C */
- /* cvoptr - convert a pointer on output */
- LOCAL OFFTYPE cvoptr(p)
- LVAL p;
- {
- OFFTYPE off = (OFFTYPE)2;
- SEGMENT *seg;
- OFFTYPE np = CVPTR(p);
- LVAL min1,max1;
- OFFTYPE min,max;
-
- /* check for nil and small fixnums */
- if (p == NIL)
- return ((OFFTYPE)p);
-
- /* compute an offset for this pointer */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- min1 = &seg->sg_nodes[0];
- max1 = &seg->sg_nodes[seg->sg_size];
- min = CVPTR(min1);
- max = CVPTR(max1);
- if (np >= min && np < max)
- return (off+ ((np-min)/sizeof(struct node)));
- off += (OFFTYPE)seg->sg_size;
- }
-
- /* pointer not within any segment */
- xlerror("bad pointer found during image save",p);
- return (0); /* fake out compiler warning */
- }
- #else
- /* cvoptr - convert a pointer on output */
- LOCAL OFFTYPE cvoptr(p)
- LVAL p;
- {
- OFFTYPE off = (OFFTYPE)2;
- SEGMENT *seg;
- OFFTYPE np = CVPTR(p);
-
- /* check for nil and small fixnums */
- if (p == NIL)
- return ((OFFTYPE)p);
-
- /* compute an offset for this pointer */
- for (seg = segs; seg != NULL; seg = seg->sg_next) {
- if (np >= CVPTR(&seg->sg_nodes[0]) &&
- np < CVPTR(&seg->sg_nodes[seg->sg_size]))
- return (off+ ((np-CVPTR(seg->sg_nodes))/sizeof(struct node)));
- off += (OFFTYPE)seg->sg_size;
- }
-
- /* pointer not within any segment */
- xlerror("bad pointer found during image save",p);
- return (0); /* fake out compiler warning */
- }
- #endif
- #endif
-
-